package com.demo.cms.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.demo.cms.dao.CategoryDao;
import com.demo.cms.model.Article;
import com.demo.cms.model.Category;
import com.demo.cms.service.ArticleService;
import com.demo.cms.service.CategoryService;
import com.demo.cms.service.exception.CategoryCreateException;
import com.demo.common.StringUtils;
import com.demo.core.dao.base.support.ResultSearchResult;
import com.demo.core.dao.base.support.SearchArgumentSupport;
import com.demo.core.model.support.AdjacencyListModel;
import com.demo.core.model.support.converter.AdjacencyListToChainedObjectConverter;

/**
 * 文章栏目服务访问实现类
 * 
 * @author ryuu.kk
 *
 */
public class CategoryServiceImpl implements CategoryService {

	/**
	 * 栏目数据访问Dao
	 */
	private CategoryDao categoryDao;
	
	/**
	 * 文章数据访问服务
	 */
	private ArticleService articleService;
	
	public Long save(Category category) throws CategoryCreateException {
		//
		return categoryDao.insert(category);
	}

	@Override
	public boolean exists(Long id) {
		return categoryDao.exists(id);
	}

	@Override
	public void delete(Long id) {
		delete(id, false);
	}

	@Override
	public void delete(Long categoryId, boolean cascade) {
		if (cascade) {
			List<Article> articleList = articleService.findList(categoryId, null);
			if (articleList != null) {
				for (Article article : articleList) {
					articleService.delete(article.getId());
				}
			}
		}
		
		categoryDao.delete(categoryId);
	}
	@Override
	public void update(Long categoryId, Category category) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("id", categoryId);
		categoryDao.update(category, params);
	}
	
	@Override
	public void updatePermission(Long categoryId, boolean isPermission) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("id", categoryId);
		categoryDao.updatePermission(isPermission, params);
	}
	
	@Override
	public void updateDraft(Long categoryId, boolean isDraft) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("id", categoryId);
		categoryDao.updateDraft(isDraft, params);
	}
	
	@Override
	public void updateStatus(Long categoryId, Category category) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("id", categoryId);
		categoryDao.updateStatus(category, params);
	}
	
	@Override
	public void update(Long categoryId, Category category, boolean isWhole) {
		update(categoryId, category);
		if (isWhole) {
			//更新其余字段
			updatePermission(categoryId, category.isPermission());
			updateDraft(categoryId, category.isDraft());
			updateStatus(categoryId, category);
		}
	}
	@Override
	public Category find(Long id) {
		return categoryDao.select(id);
	}

	@Override
	public Category find(String path) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("path", path);
		List<Category> categoryList = categoryDao.select(params);
		return categoryList.size() > 0 ? categoryList.get(0) : null;
	}
	
	@Override
	public List<Category> findList(Long channelId) {
		Map<String, Object> params = new HashMap<String, Object>(3);
		params.put("channelId", channelId);
		return categoryDao.select(params);
	}

	@Override
	public List<Category> findList(Long channelId, String i18n) {
		Map<String, Object> params = new HashMap<String, Object>(5);
		params.put("channelId", channelId);
		params.put("i18n", i18n);
		return categoryDao.select(params);
	}
	
	@Override
	public List<Category> findList(Long channelId, Long pid) {
		Map<String, Object> params = new HashMap<String, Object>(5);
		params.put("channelId", channelId);
		params.put("pid", pid);
		return categoryDao.select(params);
	}

	@Override
	public List<Category> findAll(Long siteId, String i18n) {
		return categoryDao.select(new HashMap<String, Object>());
	}
	
	@Override
	public Category findRoot(Long channelId) {
		return categoryDao.findRoot(channelId);
	}
	
	@Override
	public Category findRoot() {
		return findRoot(null);
	}

	@Override
	public ResultSearchResult<Category> search(Long channelId, Long pid, int firstResult, int maxResults) {
		Map<String, Object> params = new HashMap<String, Object>(7);
		params.put("pid", pid);
		params.put("channelId", channelId);
		SearchArgumentSupport sas = new SearchArgumentSupport(firstResult, maxResults);
		return categoryDao.search(params, sas);
	}
	
	@Override
	public ResultSearchResult<Category> search(Long channelId, Long pid, SearchArgumentSupport args) {
		Map<String, Object> params = new HashMap<String, Object>(7);
		params.put("pid", pid);
		params.put("channelId", channelId);
		return categoryDao.search(params, args);
	}
	
	@Override
	public AdjacencyListModel queryRootTree(Long channelId) {
		// ~ 使用统一栏目根节点,各栏目(即使不同频道)都将是该root节点的子节点
		// Category category = categoryDao.findRoot(channelId);
		Category category = categoryDao.findRoot();
		if (category == null) {
			//不存在频道对应的根节点
			return null;
		}
		Map<String, Object> params = new HashMap<String, Object>(3);
		params.put("id", category.getId());
		params.put("channelId", channelId);
		//包含根节点
		params.put("isRoot", true);
		List<Category> categoryList = categoryDao.tree(params);
		return AdjacencyListToChainedObjectConverter.conver(categoryList);
	}
	
	@Override
	public AdjacencyListModel queryTree(Long categoryId, int... level) {
		Map<String, Object> params = new HashMap<String, Object>();
		
		params.put("id", categoryId);
		if (level != null) {
			List<Integer> depths = new ArrayList<Integer>(level.length);
			for (int l : level) {
				depths.add(l);
			}
			params.put("depthList", depths);
		}
		List<Category> categoryList = categoryDao.tree(params);
		return AdjacencyListToChainedObjectConverter.conver(categoryList);
	}
	
	@Override
	public AdjacencyListModel queryTree(String categoryPath, int... level) {
		
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("path", categoryPath);
		if (level != null) {
			List<Integer> depths = new ArrayList<Integer>(level.length);
			for (int l : level) {
				depths.add(l);
			}
			params.put("depthList", depths);
		}
		List<Category> categoryList = categoryDao.tree(params);
		return AdjacencyListToChainedObjectConverter.conver(categoryList);
	}
	
	@Override
	public AdjacencyListModel queryTree(Long categoryId, Boolean isReverse,	int... level) {
		if (isReverse != null && isReverse) {
			Map<String, Object> params = new HashMap<String, Object>(7);
			params.put("id", categoryId);
			if (level != null) {
				List<Integer> depths = new ArrayList<Integer>(level.length);
				for (int l : level) {
					depths.add(l);
				}
				params.put("depthList", depths);
			}
			return  AdjacencyListToChainedObjectConverter.conver(categoryDao.queryReverse(params));
		} else {
			return queryTree(categoryId, level);
		}
	}

	@Override
	public AdjacencyListModel queryTree(String categoryPath, Boolean isReverse,
			int... level) {
		if (isReverse != null && isReverse) {
			Map<String, Object> params = new HashMap<String, Object>(7);
			// 指定叶子节点,从这个节点开始向上回溯到根
			params.put("nodePath", categoryPath);
			if (level != null) {
				List<Integer> depths = new ArrayList<Integer>(level.length);
				for (int l : level) {
					depths.add(l);
				}
				params.put("depthList", depths);
			}
			return  AdjacencyListToChainedObjectConverter.conver(categoryDao.queryReverse(params));
		} else {
			return queryTree(categoryPath, level);
		}
	}
	
	@Override
	public List<Category> _findList(String ssid) {
		if (StringUtils.isNotEmpty(ssid)) {
			Map<String, Object> params = new HashMap<String, Object>(3);
			params.put("channelId", Long.parseLong(ssid, 16));
			return categoryDao.select(params);
		}
		return null;
	}
	
	public void setCategoryDao(CategoryDao categoryDao) {
		this.categoryDao = categoryDao;
	}

	public void setArticleService(ArticleService articleService) {
		this.articleService = articleService;
	}
}
